﻿using System;
using System.Diagnostics;
using Oscilloscope.Util;

namespace Oscilloscope.ChannelBuffer
{
	/// <summary>
	/// 数据处理对象
	/// </summary>
	internal class MemoryChannelBuffer : IChannelBuffer, IDisposable
	{
        /// <summary>
        /// 
        /// </summary>
        /// <param name="sampleFrequency">每秒采集点数</param>
        /// <param name="timeLength">用户设定的时间</param>
        /// <param name="signalType"></param>
        /// <param name="signalRatio"></param>
        /// <exception cref="ArgumentOutOfRangeException"></exception>
        public MemoryChannelBuffer(int sampleFrequency, double timeLength, SignalType signalType, SignalRatio signalRatio)
		{

			if (sampleFrequency <= 0 || timeLength <= 0.0)
			{
				throw new ArgumentOutOfRangeException("sampleFrequency <= 0 || timeLength <= 0");
			}
			this.timeInterval = 1.0 / (double)sampleFrequency; //每个点的间隔时间
			this.signalType = signalType;
            this.signalRatio = signalRatio;
            int num = (int)Math.Ceiling(timeLength * (double)sampleFrequency) + 1; //30秒内采样的点数(总点数)
			this.buffer = new short?[num];
			this.totalTime = (double)(num - 1) * this.timeInterval; //(总点数*每个点的间隔时间) ==> 实际总时长
            this.writeIndex = -1;
			this.hasOverwrite = false;
		}

		// Token: 0x0600003E RID: 62 RVA: 0x00004B87 File Offset: 0x00002D87
		public double GetTimeInterval()
		{
			return this.timeInterval;
		}

		// Token: 0x0600003F RID: 63 RVA: 0x00004B8F File Offset: 0x00002D8F
		public double GetTotalTime()
		{
			if (this.buffer == null)
			{
				return 0.0;
			}
			return this.totalTime;
		}

		// Token: 0x06000040 RID: 64 RVA: 0x00004BA9 File Offset: 0x00002DA9
		public double GetReferenceValue()
		{
			return 0.0;
		}

		// Token: 0x06000041 RID: 65 RVA: 0x00004BB4 File Offset: 0x00002DB4
		public int GetData(double startTime, double endTime, ChannelBufferData[] buffer, int offset, ref double timeOfFirstData)
		{
			int num = 0;
			int dataByteRange = this.GetDataByteRange(startTime, endTime, ref num);
			if (dataByteRange == 0)
			{
				return 0;
			}
			if (offset + dataByteRange > buffer.Length)
			{
				throw new IndexOutOfRangeException();
			}
			int num2 = this.GetActualIndexAccordingLogicIndex(num);

            double ra = 1.0;
            switch (signalRatio)
            {
                case SignalRatio.x1:
                    ra = 1.0;
                    break;
                case SignalRatio.x10:
                    ra = 10.0;
                    break;
                case SignalRatio.x100:
                    ra = 100.0;
                    break;
                case SignalRatio.x1k:
                    ra = 1000.0;
                    break;
                case SignalRatio.x10k:
                    ra = 10000.0;
                    break;
                case SignalRatio.x100k:
                    ra = 100000.0;
                    break;
                default:
                    break;
            }

            for (int i = 0; i < dataByteRange; i++)
			{
				if (num2 >= this.buffer.Length)
				{
					num2 = 0;
				}
				if (this.signalType == SignalType.AnalogSigned)
				{
					if (this.buffer[num2] != null)
					{
						buffer[i + offset].Data = (double)this.buffer[num2].Value/ ra;
						buffer[i + offset].IsValid = true;
					}
					else
					{
						buffer[i + offset].IsValid = false;
					}
				}
				else if (this.buffer[num2] != null)
				{
					buffer[i + offset].Data = (double)((ushort)this.buffer[num2].Value)/ ra;
					buffer[i + offset].IsValid = true;
				}
				else
				{
					buffer[i + offset].IsValid = false;
				}
				num2++;
			}
			timeOfFirstData = (double)num * this.GetTimeInterval();

		//	Debug.WriteLine(timeOfFirstData);
			return dataByteRange;
		}

		// Token: 0x06000042 RID: 66 RVA: 0x00004CD4 File Offset: 0x00002ED4
		public int GetDataCount(double startTime, double endTime)
		{
			int num = 0;
			return this.GetDataByteRange(startTime, endTime, ref num);
		}

		// Token: 0x06000043 RID: 67 RVA: 0x00004CF0 File Offset: 0x00002EF0
		private int GetDataByteRange(double startTime, double endTime, ref int firstDataStartIndex)
		{
			if (startTime < 0.0 || endTime < 0.0 || endTime < startTime)
			{
				throw new ArgumentOutOfRangeException();
			}
			if (startTime == endTime || this.GetTotalTime() <= 0.0)
			{
				return 0;
			}
			double integralMultipleOfStepBaseValueOf = InternalUtils.GetIntegralMultipleOfStepBaseValueOf(startTime, this.GetTimeInterval(), false);
			double integralMultipleOfStepBaseValueOf2 = InternalUtils.GetIntegralMultipleOfStepBaseValueOf(endTime, this.GetTimeInterval(), true);
			if (integralMultipleOfStepBaseValueOf > this.GetTotalTime() || integralMultipleOfStepBaseValueOf2 < this.GetMinValidTime())
			{
				return 0;
			}
			int num = Convert.ToInt32(integralMultipleOfStepBaseValueOf / this.GetTimeInterval());
			int num2 = Convert.ToInt32(integralMultipleOfStepBaseValueOf2 / this.GetTimeInterval());
			int actualIndexAccordingLogicIndex = this.GetActualIndexAccordingLogicIndex(num2);
			if (actualIndexAccordingLogicIndex < 0)
			{
				num2 = this.buffer.Length - 1;
			}
			int i;
			for (i = num; i < num2; i++)
			{
				actualIndexAccordingLogicIndex = this.GetActualIndexAccordingLogicIndex(i);
				if (actualIndexAccordingLogicIndex >= 0)
				{
					break;
				}
			}
			if (i >= num2)
			{
				num = num2;
			}
			else
			{
				num = i;
			}
			for (i = num; i >= 0; i--)
			{
				actualIndexAccordingLogicIndex = this.GetActualIndexAccordingLogicIndex(i);
				if (actualIndexAccordingLogicIndex < 0)
				{
					i++;
					break;
				}
				if (this.buffer[actualIndexAccordingLogicIndex] != null)
				{
					break;
				}
			}
			if (i >= 0)
			{
				num = i;
			}
			for (i = num2; i <= this.buffer.Length - 1; i++)
			{
				actualIndexAccordingLogicIndex = this.GetActualIndexAccordingLogicIndex(i);
				if (actualIndexAccordingLogicIndex < 0)
				{
					i--;
					break;
				}
				if (this.buffer[actualIndexAccordingLogicIndex] != null)
				{
					break;
				}
			}
			if (i <= this.buffer.Length - 1)
			{
				num2 = i;
			}
			int result = num2 - num + 1;
			firstDataStartIndex = num;
			return result;
		}

		// Token: 0x06000044 RID: 68 RVA: 0x00004E78 File Offset: 0x00003078
		private int GetActualIndexAccordingLogicIndex(int logicIndex)
		{
			if (logicIndex < 0 || logicIndex >= this.buffer.Length)
			{
				return -1;
			}
			if (this.writeIndex < 0)
			{
				return -1;
			}
			int num = this.writeIndex + logicIndex - (this.buffer.Length - 1);
			if (num >= 0)
			{
				return num;
			}
			if (this.hasOverwrite && num + this.buffer.Length > this.writeIndex)
			{
				return num + this.buffer.Length;
			}
			return -1;
		}

		// Token: 0x06000045 RID: 69 RVA: 0x00004EE1 File Offset: 0x000030E1
		private double GetMinValidTime()
		{
			if (this.hasOverwrite)
			{
				return 0.0;
			}
			if (this.writeIndex >= 0)
			{
				return this.GetTotalTime() - (double)this.writeIndex * this.GetTimeInterval();
			}
			return double.MaxValue;
		}

		// Token: 0x06000046 RID: 70 RVA: 0x00004F1D File Offset: 0x0000311D
		public SignalType GetSignalType()
		{
			return this.signalType;
		}

		// Token: 0x06000047 RID: 71 RVA: 0x00004F28 File Offset: 0x00003128
		public void AddSampleData(short? data)
		{
			int num = (this.writeIndex + 1) % this.buffer.Length;
			if (data != null)
			{
				this.buffer[num] = new short?(data.Value);
			}
			else
			{
				this.buffer[num] = null;
			}
			if (num != this.writeIndex + 1)
			{
				this.hasOverwrite = true;
			}
			this.writeIndex = num;
		}

		// Token: 0x06000048 RID: 72 RVA: 0x00004F9A File Offset: 0x0000319A
		public IChannelBuffer Copy()
		{
			throw new NotImplementedException();
		}

		// Token: 0x06000049 RID: 73 RVA: 0x00004FA1 File Offset: 0x000031A1
		public void CopyTo(IChannelBuffer desChannelBuffer)
		{
			throw new NotImplementedException();
		}

		// Token: 0x0600004A RID: 74 RVA: 0x00004FA8 File Offset: 0x000031A8
		public void Dispose()
		{
			this.buffer = null;
			GC.Collect();
		}

		// Token: 0x04000020 RID: 32
		private double timeInterval;

		// Token: 0x04000021 RID: 33
		private double totalTime;

		// Token: 0x04000022 RID: 34
		private SignalType signalType;


		private SignalRatio signalRatio;

		// Token: 0x04000023 RID: 35
		private short?[] buffer;

		// Token: 0x04000024 RID: 36
		private int writeIndex;

		// Token: 0x04000025 RID: 37
		private bool hasOverwrite;
	}
}
